package com.dingwen.treasure.core.util;

import lombok.Builder;
import lombok.Data;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * 　ELUtil: Spring EL 表达式工具类 </br>
 * <p> 案例： </p>
 * <pre>
 *
 *
 * @Data
 * class Person {
 *     @Value("#{100 + 1}")
 *
 *     private Integer score;
 *
 *     @Value("#{'treasure'.length()}")
 *
 *     private Integer length;
 *
 *     @Value("#{new com.dingwen.treasure.core.util.TreeUtil()}")
 *     public TreeUtil tree;
 *
 *
 *
 *     private String name;
 *     private Student student;
 *
 *     public String test1() {
 *         System.out.println("test1");
 *         System.out.println(name);
 *         return "test1";
 *     }
 *
 *     public void test2() {
 *         System.out.println("test2");
 *     }
 *
 *     private void test3() {
 *         System.out.println("test2");
 *     }
 *
 *     public static void test4() {
 *         System.out.println("test4");
 *     }
 *
 *     public void test5(String test) {
 *         System.out.println(test);
 *     }
 *
 *     protected void test5() {
 *         System.out.println("test5");
 *     }
 *
 *     void test6() {
 *         System.out.println("test6");
 *     }
 *
 * }
 *
 * @Data
 * class Student {
 *     private Double score;
 *
 *     public void test7(){
 *         System.out.println("test7");
 *     }
 * }
 *
 *
 *
 *
 *       public static void main(String[] args) {
 *         // 字符串解析
 *         final String value = parse("'hello'+'world'.concat('!!!')");
 *         log.info(value);
 *
 *         Person person = new Person();
 *         person.setName("ding");
 *         Student student = new Student();
 *         student.setScore(100.0);
 *         person.setStudent(student);
 *
 *         // 对象解析
 *         final String name = parse("name", person);
 *         log.info(name);
 *
 *         final Double score = parse("student.score + 1", person);
 *         log.info(score.toString());
 *
 *         // 集合解析
 *         final Map<String, String> map = parse("{username:'tom',age:11}");
 *         log.info(map.get("username"));
 *
 *         final List list = parse("{{username:\"aaa\"},{username:'zhanfsan'}}");
 *         log.info(list.get(1).toString());
 *
 *         // 方法解析
 *         final String string = parse("test1()", person);
 *         log.info(string);
 *
 *         parse("test2()", person);
 *
 *         // 只有 public 可行
 *         //parse("test3()",person);
 *         //parse("test5()",person);
 *         //parse("test6()",person);
 *         parse("test4()", person);
 *         parse("test5('params')", person);
 *         parse("student.test7()", person);
 *
 *
 *     }
 *  </pre>
 * 　@author dingwen
 * 　@date 2022/6/27
 */
@SuppressWarnings("ALL")
@Data
@Builder
@Slf4j
@UtilityClass
public class ELUtil {

    /**
     * expressionParser
     */
    private static ExpressionParser expressionParser = new SpelExpressionParser();


    /**
     * 对象 类型解析
     *
     * @param template 样板
     * @return {@link T}
     */
    public  <T> T parse(String template, Object object) {
        EvaluationContext evaluationContext = new StandardEvaluationContext(object);
        return (T) expressionParser.parseExpression(template).getValue(evaluationContext);
    }

    /**
     * String 类型解析
     *
     * @param template 样板
     * @return {@link T}
     */
    public  <T> T parse(String template) {
        return (T) expressionParser.parseExpression(template).getValue();
    }
}




